import os
import xml.etree.ElementTree as ET
import csv
import shutil
import re
from pathlib import Path

def clear_folder(folder_path):
    """清空指定文件夹中的所有文件"""
    if folder_path.exists():
        for item in folder_path.iterdir():
            try:
                if item.is_file() or item.is_symlink():
                    item.unlink()
                elif item.is_dir():
                    shutil.rmtree(item)
            except Exception as e:
                print(f'删除 {item} 时出错: {e}')
        print(f'已清空文件夹: {folder_path}')

def extract_tables_from_xml(xml_file_path):
    """
    从XML文件中提取所有<pre>标签中的表格信息
    排除第一行的行列信息，将 " | " 替换为 ","
    在每个表格前添加表名（从前后的<p>标签中提取）
    """
    try:
        tree = ET.parse(xml_file_path)
        root = tree.getroot()
        
        # 获取所有元素的列表，包括<p>和<pre>标签
        all_elements = list(root.iter())
        
        all_tables = []
        
        # 查找所有<pre>标签
        for i, element in enumerate(all_elements):
            if element.tag == 'pre' and element.text:
                # 查找表名：在当前<pre>标签前后的<p>标签中寻找
                table_name = None
                
                # 向前查找表名（在前面的<p>标签中）
                for j in range(i-1, max(i-10, -1), -1):  # 向前查找最多10个元素
                    if all_elements[j].tag == 'p' and all_elements[j].text:
                        p_text = all_elements[j].text.strip()
                        
                        # 匹配标准格式：表数字-数字-数字 或 续表数字-数字-数字，并提取描述部分
                        match = re.search(r'续?表\d+-\d+-\d+(.+)', p_text)
                        if match:
                            # 只保留描述部分，去掉"表数字-数字-数字"前缀
                            table_name = match.group(1).strip()
                            break
                        
                        # 如果没有标准格式，查找包含"表"或"续表"的描述
                        elif '表' in p_text or '续表' in p_text:
                            # 去掉可能的"表"或"续表"前缀，保留主要描述
                            cleaned_text = re.sub(r'^续?表\s*', '', p_text).strip()
                            if cleaned_text:
                                table_name = cleaned_text
                                break
                
                # 如果前面没找到，向后查找表名
                if not table_name:
                    for j in range(i+1, min(i+10, len(all_elements))):
                        if all_elements[j].tag == 'p' and all_elements[j].text:
                            p_text = all_elements[j].text.strip()
                            
                            # 匹配标准格式并提取描述部分
                            match = re.search(r'续?表\d+-\d+-\d+(.+)', p_text)
                            if match:
                                table_name = match.group(1).strip()
                                break
                            
                            # 如果没有标准格式，查找包含"表"或"续表"的描述
                            elif '表' in p_text or '续表' in p_text:
                                cleaned_text = re.sub(r'^续?表\s*', '', p_text).strip()
                                if cleaned_text:
                                    table_name = cleaned_text
                                    break
                
                # 如果仍然没有找到表名，使用前一行作为表名
                if not table_name:
                    # 检查前一行是否以"单位"开头
                    prev_line_starts_with_unit = False
                    if i-1 >= 0 and all_elements[i-1].tag == 'p' and all_elements[i-1].text:
                        prev_text = all_elements[i-1].text.strip()
                        if prev_text.startswith('单位'):
                            prev_line_starts_with_unit = True
                    
                    if prev_line_starts_with_unit:
                        # 如果前一行以"单位"开头，使用前两行作为表名
                        table_name_parts = []
                        for j in range(i-2, max(i-3, -1), -1):  # 向前查找前两行
                            if all_elements[j].tag == 'p' and all_elements[j].text:
                                p_text = all_elements[j].text.strip()
                                if p_text:
                                    table_name_parts.append(p_text)
                                    break
                        
                        # 添加前一行（单位行）
                        if i-1 >= 0 and all_elements[i-1].tag == 'p' and all_elements[i-1].text:
                            prev_text = all_elements[i-1].text.strip()
                            if prev_text:
                                table_name_parts.append(prev_text)
                        
                        # 合并前两行作为表名
                        if table_name_parts:
                            table_name = ' '.join(table_name_parts)
                    else:
                        # 正常情况，使用前一行作为表名
                        for j in range(i-1, max(i-3, -1), -1):  # 向前查找最多3个元素
                            if all_elements[j].tag == 'p' and all_elements[j].text:
                                p_text = all_elements[j].text.strip()
                                if p_text:  # 如果有内容就使用
                                    table_name = p_text
                                    break
                
                # 处理表格数据
                lines = element.text.strip().split('\n')
                
                # 跳过第一行（行列信息，如：row_count:33  col_count:10）
                if len(lines) > 1 and ('row_count:' in lines[0] or 'col_count:' in lines[0]):
                    table_lines = lines[1:]  # 排除第一行
                else:
                    table_lines = lines
                
                # 处理表格数据
                table_data = []
                
                # 如果找到表名，添加为第一行
                if table_name:
                    table_data.append([table_name])
                
                for line in table_lines:
                    if line.strip():  # 跳过空行
                        # 将所有的 "|" 替换为 ","
                        csv_line = line.replace('|', ',')
                        # 按逗号分割成列，并去除每列的空格
                        row_data = [cell.strip() for cell in csv_line.split(',') if cell.strip()]
                        if row_data:  # 如果行有数据才添加
                            table_data.append(row_data)
                
                if table_data:  # 如果有数据才添加
                    all_tables.append(table_data)
        
        return all_tables
    
    except Exception as e:
        print(f"处理文件 {xml_file_path} 时出错: {e}")
        return []

def save_tables_to_csv(tables, csv_file_path):
    """
    将所有表格数据保存到一个CSV文件中
    """
    try:
        with open(csv_file_path, 'w', newline='', encoding='gbk', errors='replace') as csvfile:
            writer = csv.writer(csvfile)
            
            # 遍历所有表格
            for i, table in enumerate(tables):
                # 如果不是第一个表格，添加空行分隔
                if i > 0:
                    writer.writerow([])  # 空行分隔不同表格
                
                # 写入表格数据
                for row in table:
                    writer.writerow(row)
        
        # print(f"成功保存到: {csv_file_path}")
    
    except Exception as e:
        print(f"保存CSV文件 {csv_file_path} 时出错: {e}")

def batch_convert_xml_to_csv():
    """
    批量转换XML文件到CSV文件
    """
    # 定义路径
    # 使用相对路径，基于当前脚本所在目录
    current_dir = Path(__file__).parent
    xml_folder = current_dir / 'xml'
    csv_folder = current_dir / 'csv'
    
    # 清空CSV输出文件夹
    clear_folder(csv_folder)
    
    # 创建CSV输出文件夹（如果不存在）
    csv_folder.mkdir(exist_ok=True)
    
    # 遍历XML文件夹中的所有XML文件
    xml_files = list(xml_folder.glob('*.xml'))
    
    if not xml_files:
        print("未找到XML文件")
        return
    
    print(f"找到 {len(xml_files)} 个XML文件")
    
    for xml_file in xml_files:
        # print(f"\n处理文件: {xml_file.name}")
        
        # 提取表格数据
        tables = extract_tables_from_xml(xml_file)
        
        if tables:
            # 生成CSV文件路径（保持原文件名）
            csv_file_name = xml_file.stem + '.csv'
            csv_file_path = csv_folder / csv_file_name
            
            # 保存到CSV文件
            save_tables_to_csv(tables, csv_file_path)
            print(f" {xml_file.name} 中提取 {len(tables)} 个表格")
        else:
            print(f"在 {xml_file.name} 中未找到表格数据")
    
    # print(f"\n批量转换完成！CSV文件已保存到: {csv_folder}")

if __name__ == "__main__":
    batch_convert_xml_to_csv()